﻿#include <QCoreApplication>
#include <QDebug>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <QDateTime>
#include <QFile>
#include <QTextStream>
#include <QMutex>
#include <QDir>
#include <QStandardPaths>
#include "mm_service.h"
#include "crash_handler.h"

// 全局变量用于日志文件管理
static QFile* g_mmServiceLogFile = nullptr;
static QFile* g_rtcServiceLogFile = nullptr;
static QFile* g_recorderServiceLogFile = nullptr;
static QMutex g_logMutex;
static QString g_baseLogPath;
static QString g_currentDate;

// 获取当前日期字符串
QString getCurrentDateString() {
    return QDateTime::currentDateTime().toString("yyyyMMdd");
}

// 生成日志文件名
QString generateLogFileName(const QString &serviceName, const QString &date) {
    return QString("%1_%2.log").arg(serviceName, date);
}

// 获取或创建指定服务的日志文件
QFile* getOrCreateLogFile(QFile** logFile, const QString &serviceName) {
    QString currentDate = getCurrentDateString();
    
    // 如果日期改变或文件不存在，创建新文件
    if (!(*logFile) || g_currentDate != currentDate) {
        // 关闭旧文件
        if (*logFile) {
            QTextStream stream(*logFile);
            stream << QString("[%1] Log file closed due to date change\n").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"));
            stream.flush();
            (*logFile)->close();
            delete *logFile;
            *logFile = nullptr;
        }
        
        // 更新当前日期
        g_currentDate = currentDate;
        
        // 创建日志目录
        QDir logDir(g_baseLogPath);
        if (!logDir.exists()) {
            logDir.mkpath(".");
        }
        
        // 创建新的日志文件
        QString logPath = logDir.filePath(generateLogFileName(serviceName, currentDate));
        *logFile = new QFile(logPath);
        if ((*logFile)->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
            QTextStream stream(*logFile);
            stream << QString("[%1] %2 log file initialized: %3\n").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"), serviceName, logPath);
            stream.flush();
        }
    }
    
    return *logFile;
}

// 写入日志到指定文件
void writeLogToFile(QFile** logFile, const QString &serviceName, const QString &message) {
    QMutexLocker locker(&g_logMutex);
    
    QFile* file = getOrCreateLogFile(logFile, serviceName);
    if (file && file->isOpen()) {
        QTextStream stream(file);
        stream << message << "\n";
        stream.flush();
    }
}

// 分离的日志处理函数
void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
    Q_UNUSED(context);

    QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
    QString level;
    
    switch (type) {
    case QtDebugMsg:
        level = "DEBUG";
        break;
    case QtInfoMsg:
        level = "INFO";
        break;
    case QtWarningMsg:
        level = "WARNING";
        break;
    case QtCriticalMsg:
        level = "CRITICAL";
        break;
    case QtFatalMsg:
        level = "FATAL";
        break;
    }

    QString formattedMessage = QString("[%1] [%2] %3").arg(timestamp, level, msg);
    
    // 根据消息内容判断服务类型并写入对应文件
    QString lowerMsg = msg.toLower();
    
    // 1. 首先进行严格的前缀匹配（优先级最高）
    if (lowerMsg.contains("[mmservice]")) {
        // MMService日志 - 前缀匹配优先
        writeLogToFile(&g_mmServiceLogFile, "MMService", formattedMessage);
    } else if (lowerMsg.contains("[rtc]") || lowerMsg.contains("[rtc-observer]")) {
        // RTCService日志 - 前缀匹配优先
        writeLogToFile(&g_rtcServiceLogFile, "RTCService", formattedMessage);
    } else if (lowerMsg.contains("[recorder]")) {
        // RecorderService日志 - 前缀匹配优先
        writeLogToFile(&g_recorderServiceLogFile, "RecorderService", formattedMessage);
    } else {
        // 2. 然后进行关键词匹配（优先级较低）
        bool isRTC = lowerMsg.contains("rtc engine") ||
                     lowerMsg.contains("rtc client") ||
                     lowerMsg.contains("audio frame") ||
                     lowerMsg.contains("parsed channelid") ||
                     lowerMsg.contains("parsed userid") ||
                     lowerMsg.contains("parsed appid") ||
                     lowerMsg.contains("parsed token") ||
                     lowerMsg.contains("parsed gslbserver");
                     
        bool isRecorder = lowerMsg.contains("obs") ||
                         lowerMsg.contains("recording") ||
                         lowerMsg.contains("socket") ||
                         lowerMsg.contains("stream") ||
                         lowerMsg.contains("encode");
                         
        bool isMMService = lowerMsg.contains("mmservice");
        
        if (isRTC) {
            // RTCService日志
            writeLogToFile(&g_rtcServiceLogFile, "RTCService", formattedMessage);
        } else if (isRecorder) {
            // RecorderService日志
            writeLogToFile(&g_recorderServiceLogFile, "RecorderService", formattedMessage);
        } else if (isMMService) {
            // MMService日志
            writeLogToFile(&g_mmServiceLogFile, "MMService", formattedMessage);
        } else {
            // 默认归类到MMService日志（向后兼容）
            writeLogToFile(&g_mmServiceLogFile, "MMService", formattedMessage);
        }
    }
    
    // 同时输出到stderr，保持与Teacher程序的兼容性
    fprintf(stderr, "%s\n", formattedMessage.toUtf8().constData());
    fflush(stderr);

    if (type == QtFatalMsg) {
        abort();
    }
}

// 清理日志文件
void cleanupLogFiles() {
    QMutexLocker locker(&g_logMutex);
    
    if (g_mmServiceLogFile) {
        QTextStream stream(g_mmServiceLogFile);
        stream << QString("[%1] MMService log file closed\n").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"));
        stream.flush();
        g_mmServiceLogFile->close();
        delete g_mmServiceLogFile;
        g_mmServiceLogFile = nullptr;
    }
    
    if (g_rtcServiceLogFile) {
        QTextStream stream(g_rtcServiceLogFile);
        stream << QString("[%1] RTCService log file closed\n").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"));
        stream.flush();
        g_rtcServiceLogFile->close();
        delete g_rtcServiceLogFile;
        g_rtcServiceLogFile = nullptr;
    }
    
    if (g_recorderServiceLogFile) {
        QTextStream stream(g_recorderServiceLogFile);
        stream << QString("[%1] RecorderService log file closed\n").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"));
        stream.flush();
        g_recorderServiceLogFile->close();
        delete g_recorderServiceLogFile;
        g_recorderServiceLogFile = nullptr;
    }
}

int main(int argc, char *argv[])
{
    // 最早的输出，确保能看到程序启动
    fprintf(stderr, "[STARTUP] MMService main() starting...\n");
    fflush(stderr);
    
    QCoreApplication app(argc, argv);
    app.setApplicationName("ZDMMService");
    app.setApplicationVersion("1.0.0");
    app.setOrganizationName("Zaodao");

    // 命令行参数解析
    QCommandLineParser parser;
    parser.setApplicationDescription("ZD MM Service - Integrated recording and RTC service");
    parser.addHelpOption();
    parser.addVersionOption();

    QCommandLineOption rtcTypeOption(QStringList() << "r" << "rtc-type",
                                    "Service type: teacher (RTC+Recording) or student (RTC only)",
                                    "rtc-type",
                                    "teacher");
    parser.addOption(rtcTypeOption);

    // 添加录制相关参数，保持与旧版本兼容
    QCommandLineOption logOption(QStringList() << "log",
                                "Log file path for recording service",
                                "log-path");
    parser.addOption(logOption);

    QCommandLineOption crashOption(QStringList() << "crash",
                                  "Crash log file path for recording service",
                                  "crash-path");
    parser.addOption(crashOption);

    QCommandLineOption userOption(QStringList() << "user",
                                 "User name for recording service",
                                 "user-name");
    parser.addOption(userOption);

    QCommandLineOption idOption(QStringList() << "id",
                               "User ID for recording service",
                               "user-id");
    parser.addOption(idOption);

    QCommandLineOption serverOption(QStringList() << "server",
                                   "Socket server name for recording service",
                                   "server-name",
                                   "ZDTalkRecorder");
    parser.addOption(serverOption);

    QCommandLineOption recordingModeOption(QStringList() << "recording-mode",
                                           "Recording mode: device (all from device) or rtc-mic (mic from RTC callback)",
                                           "mode",
                                           "rtc-mic");
    parser.addOption(recordingModeOption);

    // RTC音频参数（仅在rtc-mic模式下使用）
    QCommandLineOption rtcAudioSampleRateOption(QStringList() << "rtc-audio-sample-rate",
                                                "RTC audio sample rate (Hz)",
                                                "sample-rate",
                                                "48000");
    parser.addOption(rtcAudioSampleRateOption);

    QCommandLineOption rtcAudioChannelsOption(QStringList() << "rtc-audio-channels",
                                              "RTC audio channels (1=mono, 2=stereo)",
                                              "channels",
                                              "2");
    parser.addOption(rtcAudioChannelsOption);

    QCommandLineOption rtcAudioFormatOption(QStringList() << "rtc-audio-format",
                                           "RTC audio format bit depth",
                                           "format",
                                           "16");
    parser.addOption(rtcAudioFormatOption);

    fprintf(stderr, "[STARTUP] Processing command line arguments...\n");
    fflush(stderr);
    parser.process(app);
    fprintf(stderr, "[STARTUP] Command line arguments processed\n");
    fflush(stderr);

    // 确定日志目录
    fprintf(stderr, "[STARTUP] Determining log directory...\n");
    fflush(stderr);
    
    QString logDirPath = parser.isSet(logOption)
        ? parser.value(logOption)
        : QCoreApplication::applicationDirPath() + "/logs/MMService";
        
    fprintf(stderr, "[STARTUP] Log directory path: %s\n", logDirPath.toUtf8().constData());
    fflush(stderr);
    
    QDir mmServiceLogDir(logDirPath);
    if (!mmServiceLogDir.exists()) {
        fprintf(stderr, "[STARTUP] Creating log directory...\n");
        fflush(stderr);
        bool created = mmServiceLogDir.mkpath(".");
        fprintf(stderr, "[STARTUP] Log directory creation result: %s\n", created ? "SUCCESS" : "FAILED");
        fflush(stderr);
    } else {
        fprintf(stderr, "[STARTUP] Log directory already exists\n");
        fflush(stderr);
    }
    
    // 设置日志基础路径
    g_baseLogPath = logDirPath;
    g_currentDate = getCurrentDateString();
    
    // 安装日志处理器
    fprintf(stderr, "[STARTUP] Installing message handler...\n");
    fflush(stderr);
    qInstallMessageHandler(messageHandler);
    fprintf(stderr, "[STARTUP] Message handler installed\n");
    fflush(stderr);
    
    qDebug() << "[MMSERVICE] Log files will be created in directory:" << logDirPath;
    qDebug() << "[MMSERVICE]   - MMService_" << g_currentDate << ".log: General service logs";
    qDebug() << "[MMSERVICE]   - RTCService_" << g_currentDate << ".log: RTC and audio device logs";
    qDebug() << "[MMSERVICE]   - RecorderService_" << g_currentDate << ".log: Recording, OBS and socket logs";

    qDebug() << "[MMSERVICE] ZDMMService starting...";
    qDebug() << "[MMSERVICE] Application:" << app.applicationName();
    qDebug() << "[MMSERVICE] Version:" << app.applicationVersion();

    // 初始化崩溃处理器
    QString crashPath = parser.isSet(crashOption)
        ? parser.value(crashOption)
        : QCoreApplication::applicationDirPath() + "/crash/MMService";
    
    // 如果传入的是文件路径（包含.txt等扩展名），提取目录部分
    QString crashDirPath;
    if (crashPath.endsWith(".txt") || crashPath.contains(".")) {
        QFileInfo fileInfo(crashPath);
        crashDirPath = fileInfo.absolutePath();
        qDebug() << "[MMSERVICE] Crash path is a file, using directory:" << crashDirPath;
    } else {
        crashDirPath = crashPath;
        qDebug() << "[MMSERVICE] Crash path is a directory:" << crashDirPath;
    }
    
    qDebug() << "[MMSERVICE] Initializing crash handler, dump directory:" << crashDirPath;
    
    if (!CrashHandler::Initialize(crashDirPath.toStdWString())) {
        qCritical() << "[MMSERVICE] Failed to initialize crash handler";
        fprintf(stderr, "[STARTUP] Failed to initialize crash handler\n");
        fflush(stderr);
        // 继续运行，但记录错误
    } else {
        qDebug() << "[MMSERVICE] Crash handler initialized successfully";
        fprintf(stderr, "[STARTUP] Crash handler initialized, dump path: %s\n", 
                crashDirPath.toUtf8().constData());
        fflush(stderr);
        
        // 设置用户信息
        QString userId = parser.value(idOption);
        QString userName = parser.value(userOption);
        if (!userId.isEmpty() && !userName.isEmpty()) {
            CrashHandler::SetUserInfo(userId.toStdString(), userName.toStdString());
        }
    }

    // 根据配置创建RTC服务
    QString rtcType = parser.value(rtcTypeOption);
    qDebug() << "[MMSERVICE] RTC Service Type:" << rtcType;

    // 创建 MMService 实例
    fprintf(stderr, "[STARTUP] Creating MMService instance...\n");
    fflush(stderr);
    MMService mmService;
    fprintf(stderr, "[STARTUP] MMService instance created\n");
    fflush(stderr);
    
    // 连接信号
    fprintf(stderr, "[STARTUP] Connecting MMService signals...\n");
    fflush(stderr);
    
    QObject::connect(&mmService, &MMService::serviceStarted, []() {
        qDebug() << "[MMSERVICE] MMService started successfully";
        fprintf(stderr, "[STARTUP] MMService started successfully\n");
        fflush(stderr);
    });
    
    QObject::connect(&mmService, &MMService::serviceStopped, [&app]() {
        qDebug() << "[MMSERVICE] MMService stopped - Teacher disconnected, exiting application";
        fprintf(stderr, "[STARTUP] MMService stopped - exiting application\n");
        fflush(stderr);
        QCoreApplication::quit();
    });
    
    QObject::connect(&mmService, &MMService::error, [](const QString &error) {
        qDebug() << "[MMSERVICE] MMService error:" << error;
        fprintf(stderr, "[STARTUP] MMService error: %s\n", error.toUtf8().constData());
        fflush(stderr);
    });
    
    fprintf(stderr, "[STARTUP] MMService signals connected\n");
    fflush(stderr);
    
    // 准备录制配置参数
    fprintf(stderr, "[STARTUP] Preparing recording configuration...\n");
    fflush(stderr);
    
    MMService::RecordingConfig config;
    config.logPath = parser.value(logOption);
    config.crashPath = parser.value(crashOption);
    config.userName = parser.value(userOption);
    config.userId = parser.value(idOption);
    config.serverName = parser.value(serverOption);
    config.recordingMode = parser.value(recordingModeOption);
    
    fprintf(stderr, "[STARTUP] Recording config prepared - mode: %s\n", config.recordingMode.toUtf8().constData());
    fflush(stderr);
    
    // RTC音频参数（仅在rtc-mic模式下有效）
    if (config.recordingMode == "rtc-mic") {
        config.rtcAudioSampleRate = parser.value(rtcAudioSampleRateOption).toInt();
        config.rtcAudioChannels = parser.value(rtcAudioChannelsOption).toInt();
        config.rtcAudioFormat = parser.value(rtcAudioFormatOption).toInt();
        
        fprintf(stderr, "[STARTUP] RTC Audio Parameters: %d Hz, %d channels, %d bit\n", 
                config.rtcAudioSampleRate, config.rtcAudioChannels, config.rtcAudioFormat);
        fflush(stderr);
        
        qDebug() << "[MMSERVICE] RTC Audio Parameters:";
        qDebug() << "[MMSERVICE]   Sample Rate:" << config.rtcAudioSampleRate << "Hz";
        qDebug() << "[MMSERVICE]   Channels:" << config.rtcAudioChannels << (config.rtcAudioChannels == 1 ? "(Mono)" : "(Stereo)");
        qDebug() << "[MMSERVICE]   Format:" << config.rtcAudioFormat << "bit";
    }
    
    // 初始化服务
    fprintf(stderr, "[STARTUP] Initializing MMService...\n");
    fflush(stderr);
    
    if (mmService.initialize(rtcType, config)) {
        qDebug() << "[MMSERVICE] MMService initialized successfully";
        fprintf(stderr, "[STARTUP] MMService initialized successfully\n");
        fflush(stderr);
        
        // 启动服务
        fprintf(stderr, "[STARTUP] Starting MMService...\n");
        fflush(stderr);
        
        mmService.start();
        
        qDebug() << "[MMSERVICE] Service type:" << mmService.getServiceType();
        fprintf(stderr, "[STARTUP] MMService started with type: %s\n", mmService.getServiceType().toUtf8().constData());
        fflush(stderr);
    } else {
        qDebug() << "[MMSERVICE] Failed to initialize MMService";
        fprintf(stderr, "[STARTUP] FAILED to initialize MMService\n");
        fflush(stderr);
        return -1;
    }

    qDebug() << "[MMSERVICE] ZDMMService is ready for development!";
    fprintf(stderr, "[STARTUP] ZDMMService is ready!\n");
    fflush(stderr);

    // 连接应用程序退出信号
    QObject::connect(&app, &QCoreApplication::aboutToQuit, []() {
        qDebug() << "[MMSERVICE] MMService shutting down, cleaning up log files...";
        fprintf(stderr, "[STARTUP] MMService shutting down...\n");
        fflush(stderr);
        
        // 清理崩溃处理器
        CrashHandler::Cleanup();
        qDebug() << "[MMSERVICE] Crash handler cleaned up";
        
        cleanupLogFiles();
    });

    fprintf(stderr, "[STARTUP] Entering event loop...\n");
    fflush(stderr);
    
    return app.exec();
} 